;
(function($, window, document, undefined) {

	'use strict';

	// Create the defaults once
	var pluginName = 'webuiPopover';
	var pluginClass = 'webui-popover';
	var pluginType = 'webui.popover';
	var defaults = {
		placement: 'auto',
		width: 'auto',
		height: 'auto',
		trigger: 'click', //hover,click,sticky,manual
		style: '',
		delay: {
			show: null,
			hide: null
		},
		async: {
			before: null, //function(that, xhr){}
			success: null //function(that, xhr){}
		},
		cache: true,
		multi: false,
		arrow: true,
		title: '',
		content: '',
		closeable: false,
		padding: true,
		url: '',
		type: 'html',
		animation: null,
		template: '<div class="webui-popover">' +
		'<div class="arrow"></div>' +
		'<div class="webui-popover-inner">' +
		'<a href="#" class="close">&times;</a>' +
		'<h3 class="webui-popover-title"></h3>' +
		'<div class="webui-popover-content"><i class="icon-refresh"></i> <p>&nbsp;</p></div>' +
		'</div>' +
		'</div>',
		backdrop: false,
		dismissible: true,
		onShow: null,
		onHide: null,
		abortXHR: true,
		autoHide: false,
		offsetTop: 0,
		offsetLeft: 0
	};


	var _srcElementsJson = {};
	var _srcElements = [];
	var backdrop = $('<div class="webui-popover-backdrop"></div>');
	var _globalIdSeed = 0;
	var _isBodyEventHandled = false;
	var _offsetOut = -2000; // the value offset  out of the screen
	var $document = $(document);

	var toNumber = function(numeric, fallback) {
		return isNaN(numeric) ? (fallback || 0) : Number(numeric);
	};

	var getPopFromElement = function($element) {
		return $element.data('plugin_' + pluginName);
	};

	var hideAllPop = function() {
		for (var i = 0; i < _srcElements.length; i++) {
			_srcElements[i].webuiPopover('hide');
		}
		$document.trigger('hiddenAll.' + pluginType);
	};




	// The actual plugin constructor
	function WebuiPopover(element, options) {
		var idstr = element.id || this.ids();
		this.$element = $(element);
		if (options) {
			if ($.type(options.delay) === 'string' || $.type(options.delay) === 'number') {
				options.delay = {
					show: options.delay,
					hide: options.delay
				}; // bc break fix
			}
		}
		this.options = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName;
		this._targetclick = false;
		this.init();
		this.$element.attr('id',idstr)
		_srcElementsJson[idstr] = this;
		_srcElements.push(this.$element);
	}

	WebuiPopover.prototype = {
		ids : function () {
			var id = 'webuipopover_lyby_';
			var index = 0;
			return function () {
				index++;
				return id+index;
			}
		}(),
		//init webui popover
		init: function() {
			//init the event handlers
			if (this.getTrigger() === 'click') {
				this.$element.off('click touchend').on('click touchend', $.proxy(this.toggle, this));
			} else if (this.getTrigger() === 'hover') {
				this.$element
					.off('mouseenter mouseleave click')
					.on('mouseenter', $.proxy(this.mouseenterHandler, this))
					.on('mouseleave', $.proxy(this.mouseleaveHandler, this));
			}
			this._poped = false;
			this._inited = true;
			this._opened = false;
			this._idSeed = _globalIdSeed;
			if (this.options.backdrop) {
				backdrop.appendTo(document.body).hide();
			}
			_globalIdSeed++;
			if (this.getTrigger() === 'sticky') {
				this.show();
			}

		},
		/* api methods and actions */
		destroy: function() {
			var index = -1;

			for (var i = 0; i < _srcElements.length; i++) {
				if (_srcElements[i] === this.$element) {
					index = i;
					break;
				}
			}

			_srcElements.splice(index, 1);


			this.hide();
			this.$element.data('plugin_' + pluginName, null);
			if (this.getTrigger() === 'click') {
				this.$element.off('click');
			} else if (this.getTrigger() === 'hover') {
				this.$element.off('mouseenter mouseleave');
			}
			if (this.$target) {
				this.$target.remove();
			}
		},
		/*
		 param: force    boolean value, if value is true then force hide the popover
		 param: event    dom event,
		 */
		hide: function(force, event) {
			if (!force && this.getTrigger() === 'sticky') {
				return;
			}

			if (!this._opened) {
				return;
			}
			if (event) {
				event.preventDefault();
				event.stopPropagation();
			}

			if (this.xhr && this.options.abortXHR === true) {
				this.xhr.abort();
				this.xhr = null;
			}


			var e = $.Event('hide.' + pluginType);
			this.$element.trigger(e, [this.$target]);
			if (this.$target) {
				this.$target.removeClass('in').addClass(this.getHideAnimation());
				var that = this;
				//setTimeout(function() {
				that.$target.hide();
				//}, 300);
			}
			if (this.options.backdrop) {
				backdrop.hide();
			}
			this._opened = false;
			this.$element.trigger('hidden.' + pluginType, [this.$target]);

			if (this.options.onHide) {
				this.options.onHide(this.$target);
			}

		},
		resetAutoHide: function() {
			var that = this;
			var autoHide = that.getAutoHide();
			if (autoHide) {
				if (that.autoHideHandler) {
					clearTimeout(that.autoHideHandler);
				}
				that.autoHideHandler = setTimeout(function() {
					that.hide();
				}, autoHide);
			}
		},
		toggle: function(e) {
			if (e) {
				e.preventDefault();
				e.stopPropagation();
			}
			this[this.getTarget().hasClass('in') ? 'hide' : 'show']();
		},
		hideAll: function() {
			hideAllPop();
		},
		/*core method ,show popover */
		show: function() {
			var
				$target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass);
			if (!this.options.multi) {
				this.hideAll();
			}
			if (this._opened) {
				return;
			}
			// use cache by default, if not cache setted  , reInit the contents 
			if (!this.getCache() || !this._poped || this.content === '') {
				this.content = '';
				this.setTitle(this.getTitle());
				if (!this.options.closeable) {
					$target.find('.close').off('click').remove();
				}
				if (!this.isAsync()) {
					this.setContent(this.getContent());
				} else {
					this.setContentASync(this.options.content);
				}
				$target.show();
			}
			this.displayContent();

			if (this.options.onShow) {
				this.options.onShow($target);
			}

			this.bindBodyEvents();
			if (this.options.backdrop) {
				backdrop.show();
			}
			this._opened = true;
			this.resetAutoHide();
		},
		displayContent: function() {
			var
			//element postion
				elementPos = this.getElementPosition(),
			//target postion
				$target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass),
			//target content
				$targetContent = this.getContentElement(),
			//target Width
				targetWidth = $target[0].offsetWidth,
			//target Height
				targetHeight = $target[0].offsetHeight,
			//placement
				placement = 'bottom',
				e = $.Event('show.' + pluginType);
			//if (this.hasContent()){
			this.$element.trigger(e, [$target]);
			//}
			if (this.options.width !== 'auto') {
				$target.width(this.options.width);
			}
			if (this.options.height !== 'auto') {
				$targetContent.height(this.options.height);
			}

			if (this.options.style) {
				this.$target.addClass(pluginClass + '-' + this.options.style);
			}

			//init the popover and insert into the document body
			if (!this.options.arrow) {
				$target.find('.arrow').remove();
			}
			$target.detach().css({
				top: _offsetOut,
				left: _offsetOut,
				display: 'block'
			});

			if (this.getAnimation()) {
				$target.addClass(this.getAnimation());
			}
			$target.appendTo(document.body);


			placement = this.getPlacement(elementPos);

			//This line is just for compatible with knockout custom binding
			this.$element.trigger('added.' + pluginType);

			this.initTargetEvents();

			if (!this.options.padding) {
				if (this.options.height !== 'auto') {
					$targetContent.css('height', $targetContent.outerHeight());
				}
				this.$target.addClass('webui-no-padding');
			}
			targetWidth = $target[0].offsetWidth;
			targetHeight = $target[0].offsetHeight;

			var postionInfo = this.getTargetPositin(elementPos, placement, targetWidth, targetHeight);

			this.$target.css(postionInfo.position).addClass(placement).addClass('in');

			if (this.options.type === 'iframe') {
				var $iframe = $target.find('iframe');
				$iframe.width($target.width()).height($iframe.parent().height());
			}




			if (!this.options.arrow) {
				this.$target.css({
					'margin': 0
				});
			}
			if (this.options.arrow) {
				var $arrow = this.$target.find('.arrow');
				$arrow.removeAttr('style');
				if (postionInfo.arrowOffset) {
					//hide the arrow if offset is negative 
					if (postionInfo.arrowOffset.left === -1 || postionInfo.arrowOffset.top === -1) {
						$arrow.hide();
					} else {
						$arrow.css(postionInfo.arrowOffset);
					}
				}
			}
			this._poped = true;
			this.$element.trigger('shown.' + pluginType, [this.$target]);
		},

		isTargetLoaded: function() {
			return this.getTarget().find('i.glyphicon-refresh').length === 0;
		},

		/*getter setters */
		getTriggerElement: function() {
			return this.$element;
		},
		getTarget: function() {
			if (!this.$target) {
				var id = pluginName + this._idSeed;
				this.$target = $(this.options.template)
					.attr('id', id)
					.data('trigger-element', this.getTriggerElement());
				this._customTargetClass = this.$target.attr('class') !== pluginClass ? this.$target.attr('class') : null;
				this.getTriggerElement().attr('data-target', id);
			}
			return this.$target;
		},
		getTitleElement: function() {
			return this.getTarget().find('.' + pluginClass + '-title');
		},
		getContentElement: function() {
			if (!this.$contentElement) {
				this.$contentElement = this.getTarget().find('.' + pluginClass + '-content');
			}
			return this.$contentElement;
		},
		getTitle: function() {
			return this.$element.attr('data-title') || this.options.title || this.$element.attr('title');
		},
		getUrl: function() {
			return this.$element.attr('data-url') || this.options.url;
		},
		getAutoHide: function() {
			return this.$element.attr('data-auto-hide') || this.options.autoHide;
		},
		getOffsetTop: function() {
			return toNumber(this.$element.attr('data-offset-top')) || this.options.offsetTop;
		},
		getOffsetLeft: function() {
			return toNumber(this.$element.attr('data-offset-left')) || this.options.offsetLeft;
		},
		getCache: function() {
			var dataAttr = this.$element.attr('data-cache');
			if (typeof(dataAttr) !== 'undefined') {
				switch (dataAttr.toLowerCase()) {
					case 'true':
					case 'yes':
					case '1':
						return true;
					case 'false':
					case 'no':
					case '0':
						return false;
				}
			}
			return this.options.cache;
		},
		getTrigger: function() {
			return this.$element.attr('data-trigger') || this.options.trigger;
		},
		getDelayShow: function() {
			var dataAttr = this.$element.attr('data-delay-show');
			if (typeof(dataAttr) !== 'undefined') {
				return dataAttr;
			}
			return this.options.delay.show === 0 ? 0 : this.options.delay.show || 100;
		},
		getHideDelay: function() {
			var dataAttr = this.$element.attr('data-delay-hide');
			if (typeof(dataAttr) !== 'undefined') {
				return dataAttr;
			}
			return this.options.delay.hide === 0 ? 0 : this.options.delay.hide || 100;
		},
		getAnimation: function() {
			var dataAttr = this.$element.attr('data-animation');
			return dataAttr || this.options.animation;
		},
		getHideAnimation: function() {
			var ani = this.getAnimation();
			return ani ? ani + '-out' : 'out';
		},
		setTitle: function(title) {
			var $titleEl = this.getTitleElement();
			if (title) {
				$titleEl.html(title);
			} else {
				$titleEl.remove();
			}
		},
		hasContent: function() {
			return this.getContent();
		},
		getContent: function() {
			if (this.getUrl()) {
				switch (this.options.type) {
					case 'iframe':
						this.content = $('<iframe frameborder="0"></iframe>').attr('src', this.getUrl());
						break;
					case 'html':
						try {
							this.content = $(this.getUrl());
							if (!this.content.is(':visible')) {
								this.content.show();
							}
						} catch (error) {
							throw new Error('Unable to get popover content. Invalid selector specified.');
						}
						break;
				}
			} else if (!this.content) {
				var content = '';
				if ($.isFunction(this.options.content)) {
					content = this.options.content.apply(this.$element[0], [this]);
				} else {
					content = this.options.content;
				}
				this.content = this.$element.attr('data-content') || content;
				if (!this.content) {
					var $next = this.$element.next();

					if ($next && $next.hasClass(pluginClass + '-content')) {
						this.content = $next;
					}
				}
			}
			return this.content;
		},
		setContent: function(content) {
			var $target = this.getTarget();
			var $ct = this.getContentElement();
			if (typeof content === 'string') {
				$ct.html(content);
			} else if (content instanceof jQuery) {
				content.removeClass(pluginClass + '-content');
				$ct.html('');
				content.appendTo($ct);
			}
			this.$target = $target;
		},
		isAsync: function() {
			return this.options.type === 'async';
		},
		setContentASync: function(content) {
			var that = this;
			if (this.xhr) {
				return;
			}
			this.xhr = $.ajax({
				url: this.getUrl(),
				type: 'GET',
				cache: this.getCache(),
				beforeSend: function(xhr) {
					if (that.options.async.before) {
						that.options.async.before(that, xhr);
					}
				},
				success: function(data) {
					that.bindBodyEvents();
					if (content && $.isFunction(content)) {
						that.content = content.apply(that.$element[0], [data]);
					} else {
						that.content = data;
					}
					that.setContent(that.content);
					var $targetContent = that.getContentElement();
					$targetContent.removeAttr('style');
					that.displayContent();
					if (that.options.async.success) {
						that.options.async.success(that, data);
					}
				},
				complete: function() {
					that.xhr = null;
				}
			});
		},

		bindBodyEvents: function() {
			if (this.options.dismissible && this.getTrigger() === 'click' && !_isBodyEventHandled) {
				$document.off('keyup.webui-popover').on('keyup.webui-popover', $.proxy(this.escapeHandler, this));
				$document.off('click.webui-popover touchend.webui-popover').on('click.webui-popover touchend.webui-popover', $.proxy(this.bodyClickHandler, this));
			}
		},

		/* event handlers */
		mouseenterHandler: function() {
			var self = this;
			if (self._timeout) {
				clearTimeout(self._timeout);
			}
			self._enterTimeout = setTimeout(function() {
				if (!self.getTarget().is(':visible')) {
					self.show();
				}
			}, this.getDelayShow());
		},
		mouseleaveHandler: function() {
			var self = this;
			clearTimeout(self._enterTimeout);
			//key point, set the _timeout  then use clearTimeout when mouse leave
			self._timeout = setTimeout(function() {
				self.hide();
			}, this.getHideDelay());
		},
		escapeHandler: function(e) {
			if (e.keyCode === 27) {
				this.hideAll();
			}
		},

		bodyClickHandler: function(e) {
			//originalEvent
			_isBodyEventHandled = true;
			var canHide = true;
			if (e.type != 'click' && e.originalEvent.changedTouches) {
				e = e.originalEvent.changedTouches[0];
			}
			for (var i = 0; i < _srcElements.length; i++) {
				var pop = getPopFromElement(_srcElements[i]);
				if (!pop) {
					_srcElementsJson[_srcElements[i].attr('id')].hide();
				}else if (pop._opened) {
					var popX1 = pop.getTarget().offset().left;
					var popY1 = pop.getTarget().offset().top;
					var popX2 = pop.getTarget().offset().left + pop.getTarget().width();
					var popY2 = pop.getTarget().offset().top + pop.getTarget().height();
					var inPop = e.pageX >= popX1 && e.pageX <= popX2 && e.pageY >= popY1 && e.pageY <= popY2;
					if (inPop) {
						canHide = false;
						break;
					}
				}
			}
			if (canHide) {
				hideAllPop();
			}
		},

		/*
		 targetClickHandler: function() {
		 this._targetclick = true;
		 },
		 */

		//reset and init the target events;
		initTargetEvents: function() {
			if (this.getTrigger() === 'hover') {
				this.$target
					.off('mouseenter mouseleave')
					.on('mouseenter', $.proxy(this.mouseenterHandler, this))
					.on('mouseleave', $.proxy(this.mouseleaveHandler, this));
			}
			this.$target.find('.close,.pill_close').off('click').on('click', $.proxy(this.hide, this, true));
			//this.$target.off('click.webui-popover').on('click.webui-popover', $.proxy(this.targetClickHandler, this));
		},
		/* utils methods */
		//caculate placement of the popover
		getPlacement: function(pos) {
			var
				placement,
				de = document.documentElement,
				db = document.body,
				clientWidth = de.clientWidth,
				clientHeight = de.clientHeight,
				scrollTop = Math.max(db.scrollTop, de.scrollTop),
				scrollLeft = Math.max(db.scrollLeft, de.scrollLeft),
				pageX = Math.max(0, pos.left - scrollLeft),
				pageY = Math.max(0, pos.top - scrollTop);
			//arrowSize = 20;

			//if placement equals auto，caculate the placement by element information;
			if (typeof(this.options.placement) === 'function') {
				placement = this.options.placement.call(this, this.getTarget()[0], this.$element[0]);
			} else {
				placement = this.$element.data('placement') || this.options.placement;
			}

			var isH = placement === 'horizontal';
			var isV = placement === 'vertical';
			var detect = placement === 'auto' || isH || isV;

			if (detect) {
				if (pageX < clientWidth / 3) {
					if (pageY < clientHeight / 3) {
						placement = isH ? 'right-bottom' : 'bottom-right';
					} else if (pageY < clientHeight * 2 / 3) {
						if (isV) {
							placement = pageY <= clientHeight / 2 ? 'bottom-right' : 'top-right';
						} else {
							placement = 'right';
						}
					} else {
						placement = isH ? 'right-top' : 'top-right';
					}
					//placement= pageY>targetHeight+arrowSize?'top-right':'bottom-right';
				} else if (pageX < clientWidth * 2 / 3) {
					if (pageY < clientHeight / 3) {
						if (isH) {
							placement = pageX <= clientWidth / 2 ? 'right-bottom' : 'left-bottom';
						} else {
							placement = 'bottom';
						}
					} else if (pageY < clientHeight * 2 / 3) {
						if (isH) {
							placement = pageX <= clientWidth / 2 ? 'right' : 'left';
						} else {
							placement = pageY <= clientHeight / 2 ? 'bottom' : 'top';
						}
					} else {
						if (isH) {
							placement = pageX <= clientWidth / 2 ? 'right-top' : 'left-top';
						} else {
							placement = 'top';
						}
					}
				} else {
					//placement = pageY>targetHeight+arrowSize?'top-left':'bottom-left';
					if (pageY < clientHeight / 3) {
						placement = isH ? 'left-bottom' : 'bottom-left';
					} else if (pageY < clientHeight * 2 / 3) {
						if (isV) {
							placement = pageY <= clientHeight / 2 ? 'bottom-left' : 'top-left';
						} else {
							placement = 'left';
						}
					} else {
						placement = isH ? 'left-top' : 'top-left';
					}
				}
			} else if (placement === 'auto-top') {
				if (pageX < clientWidth / 3) {
					placement = 'top-right';
				} else if (pageX < clientWidth * 2 / 3) {
					placement = 'top';
				} else {
					placement = 'top-left';
				}
			} else if (placement === 'auto-bottom') {
				if (pageX < clientWidth / 3) {
					placement = 'bottom-right';
				} else if (pageX < clientWidth * 2 / 3) {
					placement = 'bottom';
				} else {
					placement = 'bottom-left';
				}
			} else if (placement === 'auto-left') {
				if (pageY < clientHeight / 3) {
					placement = 'left-top';
				} else if (pageY < clientHeight * 2 / 3) {
					placement = 'left';
				} else {
					placement = 'left-bottom';
				}
			} else if (placement === 'auto-right') {
				if (pageY < clientHeight / 3) {
					placement = 'right-top';
				} else if (pageY < clientHeight * 2 / 3) {
					placement = 'right';
				} else {
					placement = 'right-bottom';
				}
			}
			return placement;
		},
		getElementPosition: function() {
			return $.extend({}, this.$element.offset(), {
				width: this.$element[0].offsetWidth,
				height: this.$element[0].offsetHeight
			});
		},

		getTargetPositin: function(elementPos, placement, targetWidth, targetHeight) {
			var pos = elementPos,
				de = document.documentElement,
				db = document.body,
				clientWidth = de.clientWidth,
				clientHeight = de.clientHeight,
				elementW = this.$element.outerWidth(),
				elementH = this.$element.outerHeight(),
				scrollTop = Math.max(db.scrollTop, de.scrollTop),
				scrollLeft = Math.max(db.scrollLeft, de.scrollLeft),
				position = {},
				arrowOffset = null,
				arrowSize = this.options.arrow ? 20 : 0,
				padding = 10,
				fixedW = elementW < arrowSize + padding ? arrowSize : 0,
				fixedH = elementH < arrowSize + padding ? arrowSize : 0,
				refix = 0,
				pageH = clientHeight + scrollTop,
				pageW = clientWidth + scrollLeft;



			var validLeft = pos.left + pos.width / 2 - fixedW > 0;
			var validRight = pos.left + pos.width / 2 + fixedW < pageW;
			var validTop = pos.top + pos.height / 2 - fixedH > 0;
			var validBottom = pos.top + pos.height / 2 + fixedH < pageH;

			switch (placement) {
				case 'bottom':
					position = {
						top: pos.top + pos.height,
						left: pos.left + pos.width / 2 - targetWidth / 2
					};
					break;
				case 'top':
					position = {
						top: pos.top - targetHeight,
						left: pos.left + pos.width / 2 - targetWidth / 2
					};
					break;
				case 'left':
					position = {
						top: pos.top + pos.height / 2 - targetHeight / 2,
						left: pos.left - targetWidth
					};
					break;
				case 'right':
					position = {
						top: pos.top + pos.height / 2 - targetHeight / 2,
						left: pos.left + pos.width
					};
					break;
				case 'top-right':
					position = {
						top: pos.top - targetHeight,
						left: validLeft ? pos.left - fixedW : padding
					};
					arrowOffset = {
						left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut
					};
					break;
				case 'top-left':
					refix = validRight ? fixedW : -padding;
					position = {
						top: pos.top - targetHeight,
						left: pos.left - targetWidth + pos.width + refix
					};
					arrowOffset = {
						left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut
					};
					break;
				case 'bottom-right':
					position = {
						top: pos.top + pos.height,
						left: validLeft ? pos.left - fixedW : padding
					};
					arrowOffset = {
						left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut
					};
					break;
				case 'bottom-left':
					refix = validRight ? fixedW : -padding;
					position = {
						top: pos.top + pos.height,
						left: pos.left - targetWidth + pos.width + refix
					};
					arrowOffset = {
						left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut
					};
					break;
				case 'right-top':
					refix = validBottom ? fixedH : -padding;
					position = {
						top: pos.top - targetHeight + pos.height + refix,
						left: pos.left + pos.width
					};
					arrowOffset = {
						top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut
					};
					break;
				case 'right-bottom':
					position = {
						top: validTop ? pos.top - fixedH : padding,
						left: pos.left + pos.width
					};
					arrowOffset = {
						top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut
					};
					break;
				case 'left-top':
					refix = validBottom ? fixedH : -padding;
					position = {
						top: pos.top - targetHeight + pos.height + refix,
						left: pos.left - targetWidth
					};
					arrowOffset = {
						top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut
					};
					break;
				case 'left-bottom':
					position = {
						top: validTop ? pos.top - fixedH : padding,
						left: pos.left - targetWidth
					};
					arrowOffset = {
						top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut
					};
					break;

			}
			position.top += this.getOffsetTop();
			position.left += this.getOffsetLeft();

			return {
				position: position,
				arrowOffset: arrowOffset
			};
		}
	};
	$.fn[pluginName] = function(options, noInit) {
		var results = [];
		var $result = this.each(function() {

			var webuiPopover = $.data(this, 'plugin_' + pluginName);
			if (!webuiPopover) {
				if (!options) {
					webuiPopover = new WebuiPopover(this, null);
				} else if (typeof options === 'string') {
					if (options !== 'destroy') {
						if (!noInit) {
							webuiPopover = new WebuiPopover(this, null);
							results.push(webuiPopover[options]());
						}
					}
				} else if (typeof options === 'object') {
					webuiPopover = new WebuiPopover(this, options);
				}
				$.data(this, 'plugin_' + pluginName, webuiPopover);
			} else {
				if (options === 'destroy') {
					webuiPopover.destroy();
				} else if (typeof options === 'string') {
					results.push(webuiPopover[options]());
				}
			}
		});

		return (results.length) ? results : $result;
	};

})(jQuery, window, document);
